#include <iostream>
#include <sys/types.h>
#include <unistd.h>
#include <string>
#include <sys/types.h>
#include <sys/wait.h>
/*
(1) 管道正常 && 管道为空 -> 读端阻塞
(2) 管道正常 && 管道已满 -> 写端写满之后不在写入。
(3) 管道正常 && 写端关闭 -> 读端返回0
(4) 管道正常 && 读端关闭 -> OS杀掉写段 kill -13 + pid 

管道特征： (在内核缓冲区当中，没有刷新到磁盘当中)
1. 单向通信🤩
2. 不会产生冲突，写端写入的时候，读端不会把数据读走🤩
3. 文件的声明周期随进程 ->🤔
....
    🤔🤔🤔
*/
int main()
{
    // 创建管道
    int fds[2] = {0};
    int n = pipe(fds);
    if (n < 0)
    {
        printf("创建管道失败!\n");
        return 1;
    }
    // 创建子进程
    // 子进程进行写入
    // 父进程读写
    pid_t id = fork();
    if (id < 0)
    {
        printf("创建子进程失败!\n");
        return 2;
    }
    if (id == 0)
    {
        // 子进程
        close(fds[0]); // close (read)
        int cnt = 0;   // 统计次数的
        int total = 0; // 统计写入的总数
        while (true)
        {
            // 子进程持续不断地写入
            std::string message = "hello bit ";
            message += std::to_string(getpid()) + " ";
            message += std::to_string(cnt++);
            // sleep(5); (1) 管道正常 && 写端阻塞 -> 读端阻塞
            // sleep(5);
            total += ::write(fds[1], message.c_str(), message.size());
            printf("total: %d\n", total);
            // sleep(1);
            // break;
        }
        //(3) 管道正常 && 写端关闭 -> 读端返回0
        close(fds[1]); // 通信完毕,关闭写端
        exit(0);
    }
    else
    {
        // 父进程
        close(fds[1]); // 关闭 write
        while (true)
        {
            // sleep(100); (2) 管道正常 && 读端阻塞 -> 写端写满之后不在写入。
            char buffer[1024] = {0};
            printf("等待写端写入数据......\n");
            int len = ::read(fds[0], buffer, 1024);
            if (len > 0)
            {
                buffer[len] = 0;
                printf("buffer: %s\n", buffer);
            }
            else
            {
                break;
                printf("write close??? ,len: %d\n", len);
            }
            sleep(2);
            // break; // (4) 管道正常 && 读端关闭 -> OS杀掉写段 kill -13 + pid 
        }
        close(fds[0]); // 通信完毕,关闭读端
        int status = 0;
        waitpid(id,&status,0);
        if (id < 0) 
        {
            printf("等待子进程失败!\n");
            exit(1);
        }
        printf("wait child : %d successful, exit code : %d, exit sigl: %d\n", id, (status >> 8)&(0xff),status & (0x7f));
        exit(0);
    }

    return 0;
}
